package com.cenntro.common.httpclient;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.Consts;
import org.apache.http.HeaderIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

public class HttpsUtils {
	private static final String HTTP = "http";
	private static final String HTTPS = "https";
	private static SSLConnectionSocketFactory sslsf = null;
	private static PoolingHttpClientConnectionManager cm = null;
	private static SSLContextBuilder builder = null;
	public static Logger LOG = LoggerFactory.getLogger(HttpsUtils.class);
	static {
		try {
			builder = new SSLContextBuilder();
			// 全部信任 不做身份鉴定
			builder.loadTrustMaterial(null, new TrustStrategy() {
				@Override
				public boolean isTrusted(X509Certificate[] x509Certificates,
						String s) throws CertificateException {
					return true;
				}
			});
			sslsf = new SSLConnectionSocketFactory(builder.build(),
					new String[] { "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2" },
					null, NoopHostnameVerifier.INSTANCE);
			Registry<ConnectionSocketFactory> registry = RegistryBuilder
					.<ConnectionSocketFactory> create()
					.register(HTTP, new PlainConnectionSocketFactory())
					.register(HTTPS, sslsf).build();
			cm = new PoolingHttpClientConnectionManager(registry);
			cm.setMaxTotal(200);// max connection
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * httpClient post请求
	 * 
	 * @param url
	 *            请求url
	 * @param header
	 *            头部信息
	 * @param param
	 *            请求参数 form提交适用
	 * @param entity
	 *            请求实体 json/xml提交适用
	 * @return 可能为空 需要处理
	 * @throws Exception
	 *
	 */
	public static String post(String  url, Map<String, String> header, Map<String, String> param, HttpEntity entity) {
        String result = "";
        CloseableHttpClient httpClient = null;
        try {
            httpClient = getHttpClient();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("charset", "UTF-8");
//            RequestConfig config = RequestConfig.custom().setConnectTimeout(6000).setSocketTimeout(6000)  
//    	            .setCookieSpec(CookieSpecs.STANDARD).build(); 
//            
//    
//            httpPost.setConfig(config);
            // 设置头信息
            if (header != null) {
                for (Map.Entry<String, String> entry : header.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            // 设置请求参数
            if (param != null) {
                List<NameValuePair> formparams = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> entry : param.entrySet()) {
                    //给参数赋值
                    formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
                httpPost.setEntity(urlEncodedFormEntity);
            }
            // 设置实体 优先级高
            if (entity != null) {
                httpPost.setEntity(entity);
            }
            HttpResponse httpResponse = httpClient.execute(httpPost);
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                HttpEntity resEntity = httpResponse.getEntity();
                result = EntityUtils.toString(resEntity);
            } else {
            	readHttpResponse(httpResponse);
            }
            System.out.println("response:" + statusCode+  ",result :" + result);
        } catch (Exception e) {
        	LOG.error("", e);
        	e.printStackTrace();
        } finally {
            if (httpClient != null) {
                try {
					httpClient.close();
                	LOG.info("Available : Available={},Leased = {},MaxTotal={}" , cm.getTotalStats().getAvailable() , cm.getTotalStats().getLeased(), cm.getMaxTotal());
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }
        }
        return result;
    }

	public static CloseableHttpClient getHttpClient() throws Exception {
		RequestConfig requestConfig = RequestConfig.custom().
			    setConnectionRequestTimeout(1000).setConnectTimeout(1000).setSocketTimeout(1000).build();
		CloseableHttpClient httpClient = HttpClients.custom()
				.setSSLSocketFactory(sslsf).setConnectionManager(cm)
				.setConnectionManagerShared(true).setDefaultRequestConfig(requestConfig).build();
		return httpClient;
	}

	public static String readHttpResponse(HttpResponse httpResponse)
			throws ParseException, IOException {
		StringBuilder builder = new StringBuilder();
		// 获取响应消息实体
		HttpEntity entity = httpResponse.getEntity();
		// 响应状态
		builder.append("status:" + httpResponse.getStatusLine());
		builder.append("headers:");
		HeaderIterator iterator = httpResponse.headerIterator();
		while (iterator.hasNext()) {
			builder.append("\t" + iterator.next());
		}
		// 判断响应实体是否为空
		if (entity != null) {
			String responseString = EntityUtils.toString(entity);
			builder.append("response length:" + responseString.length());
			builder.append("response content:"
					+ responseString.replace("\r\n", ""));
		}
		return builder.toString();
	}
	
	/**
	 * 
	 * @param obj
	 * @return
	 */
	public static HttpEntity getHttpEntity(Object obj){
		MultipartEntityBuilder builder = MultipartEntityBuilder.create();
		JSONObject json = JSONObject.parseObject(obj.toString());
		Iterator<Map.Entry<String, Object>> it = json.entrySet().iterator();
		while(it.hasNext()){
			Entry<String, Object> entry = it.next();
			try {
				String value =	URLEncoder.encode(entry.getValue().toString(), "utf-8");
				StringBody  legality = new StringBody(value, ContentType.TEXT_PLAIN);
				builder.addPart(entry.getKey(), legality);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		builder.setContentType(ContentType.MULTIPART_FORM_DATA);
		builder.setCharset(Charset.forName("utf-8"));
		return builder.build();
	}
}